// 2025/5/27: 首个版本
// 2025/5/28: 优化策略
// 2025/6/3: Level变化时打印
// 2025/6/4: 新增UpdateReceiveInterval

using System;
using System.Collections.Generic;
using ASEva;

namespace RemoteConsole
{
    class RandomSkipper(Dictionary<int, LevelProfile> levelProfiles, int levelDownThreshold/* ms */, int doubleLevelDownThreshold/* ms */, int levelUpThreshold/* ms */, int receiveIntervalTriggerThreshold/* ms */, int receiveIntervalResetTime/* sec */, int receiveIntervalDownLevel)
    {
        public void Enable()
        {
            enable = true;
        }

        public void Disable()
        {
            enable = false;
        }

        public void UpdateLastRoundTripTime(int time)
        {
            if (!enable)
            {
                okCount = 0;
                lastRoundTripTime = 0;
                return;
            }

            if (time > levelDownThreshold)
            {
                okCount = 0;
                var targetLevel = Math.Max(0, level - (time > doubleLevelDownThreshold ? 2 : 1) + (time > lastRoundTripTime ? 0 : 1));
                lastRoundTripTime = time;
                if (targetLevel != level)
                {
                    level = targetLevel;
                    var msg = DateTime.Now.ToString("HH:mm:ss") + " Data skip level increased to " + (maxLevel - level)/* 避免混淆 */;
                    if (Logger == null) AgencyLocal.Print(msg);
                    else Logger.Print(msg);
                }
                return;
            }

            if (time < levelUpThreshold)
            {
                if (++okCount >= 10)
                {
                    okCount = 0;
                    lastRoundTripTime = time;
                    var targetLevel = Math.Min(maxLevel, level + 1);
                    if (targetLevel != level)
                    {
                        level = targetLevel;
                        var msg = DateTime.Now.ToString("HH:mm:ss") +  " Data skip level decreased to " + (maxLevel - level)/* 避免混淆 */;
                        if (Logger == null) AgencyLocal.Print(msg);
                        else Logger.Print(msg);
                    }
                    return;
                }
            }
            else okCount = 0;
        }

        public void UpdateReceiveInterval(int receiveInterval)
        {
            if (!enable)
            {
                lastReceiveIntervalTriggerTime = new DateTime();
                return;
            }

            var now = DateTime.Now;
            if (now < lastReceiveIntervalTriggerTime) lastReceiveIntervalTriggerTime = now;

            if (now > lastReceiveIntervalTriggerTime.AddSeconds(receiveIntervalResetTime))
            {
                if (receiveInterval > receiveIntervalTriggerThreshold)
                {
                    lastReceiveIntervalTriggerTime = now;
                    var targetLevel = Math.Max(0, level - receiveIntervalDownLevel);
                    if (targetLevel != level)
                    {
                        level = targetLevel;
                        var msg = DateTime.Now.ToString("HH:mm:ss") + " Data skip level increased to " + (maxLevel - level)/* 避免混淆 */;
                        if (Logger == null) AgencyLocal.Print(msg);
                        else Logger.Print(msg);
                    }
                }
            }
        }

        public bool TestGeneralSample()
        {
            return random.NextDouble() <= levelProfiles[level].GeneralSampleRatio;
        }

        public bool TestSmallerBusMessage()
        {
            return random.NextDouble() <= levelProfiles[level].SmallerBusMessageRatio;
        }

        public bool TestLargerBusMessage()
        {
            return random.NextDouble() <= levelProfiles[level].LargerBusMessageRatio;
        }

        public bool TestVideoFrame()
        {
            return random.NextDouble() <= levelProfiles[level].VideoFrameRatio;
        }

        public bool TestAudioFrame()
        {
            return random.NextDouble() <= levelProfiles[level].AudioFrameRatio;
        }

        public bool TestPointCloud()
        {
            return random.NextDouble() <= levelProfiles[level].PointCloudRatio;
        }

        private bool enable = false;
        private int maxLevel = levelProfiles.Keys.Count - 1;
        private int level = levelProfiles.Keys.Count - 1;
        private int okCount = 0;
        private int lastRoundTripTime = 0;
        private Random random = new Random(DateTime.Now.ToString().GetHashCode());
        private DateTime lastReceiveIntervalTriggerTime;

        public static Logger Logger { private get; set; }
    }

    class LevelProfile(double generalSampleRatio, double smallerBusMessageRatio, double largerBusMessageRatio, double videoFrameRatio, double audioFrameRatio, double pointCloudRatio)
    {
        public double GeneralSampleRatio => generalSampleRatio;
        public double SmallerBusMessageRatio => smallerBusMessageRatio;
        public double LargerBusMessageRatio => largerBusMessageRatio;
        public double VideoFrameRatio => videoFrameRatio;
        public double AudioFrameRatio => audioFrameRatio;
        public double PointCloudRatio => pointCloudRatio;
    }
}